<!DOCTYPE html>
<html lang="en" >
<head>
  <meta charset="UTF-8">
  <title>Retail in the Metaverse</title>
  <script src="7eb4b02976.js" crossorigin="anonymous">
      </script><link rel='stylesheet' href='bootstrap.min.css'>
    <link rel="stylesheet" href="./style.css">
</head>
<body>
    <!-- partial:index.partial.html -->
    <div id="loading">
        <h2>Loading...</h2>
        <div class="spinner"></div>
    </div>

    <div id="overlay" />
    <!-- partial -->
    <script src='three.min.js'></script>
    <script src='OrbitControls.js'></script>
    <script src='GLTFLoader.js'></script>
    <script src='FBXLoader.js'></script>
    <script src='index.min.js'></script>
    <script src='tween.umd.js'></script>
    <script src='react.production.min.js'></script>
    <script src='react-dom.production.min.js'></script>
    <script src='react-bootstrap.min.js'></script>
    <script src="./script.js"></script>
    <canvas id="mycanvas" width="1000" height="800" style="position: fixed; left: 800px; top: 0px; display:none;"/>
    <script type="text/javascript" src="facecat.js"></script>
    <script type="text/javascript">
        let canvas = document.getElementById("mycanvas"); //绘图区域
        canvas.width = window.innerWidth;
        canvas.height = window.innerHeight;
        let gPaint = new FCPaint(); //绘图对象
        gPaint.canvas = canvas;
        scaleCanvas(gPaint);
        //判断是否移动端
        gPaint.isMobile = isMobileMode();
        if (gPaint.isMobile) {
            gPaint.scaleFactorX = 2.5;
            gPaint.scaleFactorY = 2.5;
        }
        
        gPaint.defaultUIStyle = "dark";
        addDefaultEvent(canvas, gPaint);

        /*
        * 点击方法
        * view:视图
        * firstTouch:是否第一次触摸
        * firstPoint:第一次触摸的坐标
        * secondTouch:是否第二次触摸
        * secondPoint:第二次触摸的坐标
        * clicks:点击次数
        */
        gPaint.onClick = function (view, firstTouch, firstPoint, secondTouch, secondPoint, clicks) {
            onClickDefault(view, firstTouch, firstPoint, secondTouch, secondPoint, clicks);
            if (view.viewName) { 
                if (view.viewName.indexOf("Indicator_") == 0) {
                    if (view.text == "BOLL" || view.text == "MA") {
                        chart.mainIndicator = view.text;
                    } else {
                        chart.showIndicator = view.text;
                    }
                    calcChartIndicator(chart);
                    invalidateView(chart);
                } else if (view.viewName.indexOf("Plot_") == 0) {
                    chart.addingPlot = view.viewName.substring(5);
                }
            }
        };

        /*
        * 鼠标按下实现方法
        * view:视图
        * mp:坐标
        * button:按钮
        * clicks:点击次数
        * delta:滚轮值
        */
        gPaint.onMouseDown = function (view, mp, buttons, clicks, delta) {
            if (view.viewType == "chart") {
                if (!view.datas || view.datas.length == 0) {
                    return;
                }
                if (view.addingPlot.length > 0) {
                    addPlotDefault(view, true, mp, false, mp);
                    view.addingPlot = "";
                    invalidateView(chart);
                } else {
                    touchDownChart(view, true, mp, false, mp);
                    invalidateView(chart);
                }
            }else{
                onMouseDownDefault(view, mp, buttons, clicks, delta);
            }
        };

        /*
        * 触摸开始方法
        * view:视图
        * firstTouch:是否第一次触摸
        * firstPoint:第一次触摸的坐标
        * secondTouch:是否第二次触摸
        * secondPoint:第二次触摸的坐标
        */
        gPaint.onTouchBegin = function (view, firstTouch, firstPoint, secondTouch, secondPoint) {
            if (view.viewType == "chart") {
                if (!view.datas || view.datas.length == 0) {
                    return;
                }
                if (view.addingPlot.length > 0) {
                    addPlotDefault(view, firstTouch, firstPoint, secondTouch, secondPoint);
                    view.addingPlot = "";
                    invalidateView(chart);
                } else {
                    touchDownChart(view, firstTouch, firstPoint, secondTouch, secondPoint);
                    invalidateView(chart);
                }
            }else{
                onTouchBeginDefault(view, firstTouch, firstPoint, secondTouch, secondPoint);
            }
        };

        /**
         * 绘制横轴刻度的自定义方法
         * chart:图表
         * paint:绘图对象
         * clipRect:裁剪区域
         * 该逻辑仅针对日K线 
         */
         gPaint.onPaintChartHScale = function(chart, paint, clipRect){
            if (chart.datas && chart.datas.length > 0 && chart.hScaleHeight > 0) {
                let drawLeft = chart.leftVScaleWidth; //左侧起画点
                let i = chart.firstVisibleIndex; //开始索引
                let lastYear = 0; //缓存年份，用于判断是否换年
                let drawYearsCache = []; //实际绘制到图形上的年份文字
                let lastTextRight = 0; //上个文字的右侧
                let timeCache = []; //保存日期的缓存
                let yearTextLeftCache = []; //绘制年文字的左侧位置缓存
                let yearTextRightCache = []; //绘制年文字的右侧位置缓存
                let textPadding = 5; //两个文字之间的最小间隔
                //逐步递增索引，先绘制年
                while(i <= chart.lastVisibleIndex){
                    let dateObj = new Date();
				    dateObj.setTime(chart.datas[i].date); //将时间戳转换为time，并缓存到集合中
                    timeCache.push(dateObj);
                    let year = dateObj.getFullYear(); //从结构中获取年份			
                    let x = getChartX(chart, i); //获取索引对应的位置
                    //判断是否换年，以及是否在绘图区间内
                    if (year != lastYear && x >= drawLeft && x < chart.size.cx - chart.rightVScaleWidth){
                        let month = dateObj.getMonth() + 1; //获取月的结构
                        let xText = year.toString(); //拼接要绘制的文字
                        if (month < 10){
                            xText = xText + "/0" + month.toString(); //如果小于10月要补0
                        }
                        else{
                            xText = xText + "/" + month.toString(); //大于等于10月不用补0
                        }
                        let tSize = paint.textSize(xText, chart.font); //计算要绘制文字的大小
                        paint.drawLine(chart.scaleColor, 1, 0, x, chart.size.cy - chart.hScaleHeight, x, chart.size.cy - chart.hScaleHeight + 8) //绘制刻度线
                        //判断是否和上个文字重影
                        if (x - tSize.cx / 2 > lastTextRight + textPadding){
                            paint.drawText(xText, chart.hScaleTextColor, "Default,12", x - tSize.cx / 2, chart.size.cy - chart.hScaleHeight + 8  - tSize.cy / 2 + 7) //绘制文字
                            yearTextLeftCache.push(x - tSize.cx / 2); //将年文字的左侧位置缓存
                            yearTextRightCache.push(x + tSize.cx / 2); //将年文字的右侧位置缓存
                            drawYearsCache.push(year); //缓存要绘制的年
                            lastTextRight = x + tSize.cx / 2; //缓存上个文字的右侧位置
                        }
                        lastYear = year; //记录上次绘制的年份
                    }
                    i = i + 1;	//索引累加
                }	
                //绘制月份
                for(let m = 0; m < drawYearsCache.length; m++){
                    let cacheYear = drawYearsCache[m]; //从缓存中获取年份
                    let lastMonth = 0; //缓存月份，用于判断是否换月
                    i = chart.firstVisibleIndex; //重置开始索引
                    lastTextRight = 0; //重置上个文字的右侧
                    //逐步递增索引
                    while (i <= chart.lastVisibleIndex){
                        let dateObj = timeCache[i - chart.firstVisibleIndex]; //从缓存中获取time
                        let year = dateObj.getFullYear(); //从结构中获取年份
                        //判断是否同一年	
                        if (cacheYear == year){
                            let month = dateObj.getMonth() + 1; //从结构中获取月份
                            let x = getChartX(chart, i);
                            //判断是否换月，以及是否在绘图区间内
                            if(lastMonth != month && x >= drawLeft && x < chart.size.cx - chart.rightVScaleWidth){		
                                let xText = month.toString(); //获取绘制的月份文字
                                let tSize = paint.textSize(xText, chart.font); //计算要绘制文字的大小
                                //判断是否和上个文字重影
                                if(x - tSize.cx / 2 > lastTextRight + textPadding){
                                    if ((x - tSize.cx / 2 > yearTextRightCache[m] + textPadding) 
                                    && ((m == drawYearsCache.length - 1) 
                                    || ((m < drawYearsCache.length - 1) 
                                    && (x + tSize.cx / 2 < yearTextLeftCache[m + 1] - textPadding)))){
                                        paint.drawLine(chart.scaleColor, 1, 0, x, chart.size.cy - chart.hScaleHeight, x, chart.size.cy - chart.hScaleHeight + 6); //绘制刻度
                                        paint.drawText(xText, chart.hScaleTextColor, "Default,12", x - tSize.cx / 2, chart.size.cy - chart.hScaleHeight + 8  - tSize.cy / 2 + 7); //绘制文字
                                        lastTextRight = x + tSize.cx / 2; //缓存上个文字的右侧位置
                                    }
                                }
                                lastMonth = month //记录上次绘制的月份
                            }
                        }
                        else if(cacheYear < year){
                            break; //超过区间，退出循环
                        }
                        i = i + 1;	//索引累加
                    }
                }
            }
        };

        /*
         * 重置大小
         */
        let resizeAll = function () {
            try {
                canvas.width = document.documentElement.clientWidth;
                canvas.height = document.documentElement.clientHeight;
                scaleCanvas(gPaint);
                updateViewDefault(gPaint.views);
            } catch (err) {
                
            }
            invalidate(gPaint);
        };


        /*
        * 监听大小改变
        */
        window.onresize = function () {
            resizeAll();
        };

        /*
        * 旋转监听
        */
        window.onorientationchange = function () {
            resizeAll();
        };

        //解析加载XML
        let xml = `<?xml version="1.0" encoding="utf-8"?>
        <html xmlns="facecat">
          <body>
            <div type="splitlayout" layoutstyle="toptobottom" bordercolor="none" dock="fill" size="400,400" candragsplitter="true" splitterposition="25,1">
              <div type="layout" backcolor="none" bordercolor="none">
                <select name="cbIndicator" selectedindex="0" size="80,25">
                  <option text="MA" name="Indicator_MA" />
                  <option text="BOLL" name="Indicator_BOLL" />
                  <option text="MACD" name="Indicator_MACD" />
                  <option text="KDJ" name="Indicator_KDJ" />
                  <option text="BIAS" name="Indicator_BIAS" />
                  <option text="BBI" name="Indicator_BBI" />
                  <option text="RSI" name="Indicator_RSI" />
                  <option text="ROC" name="Indicator_ROC" />
                  <option text="WR" name="Indicator_WR" />
                  <option text="DMA" name="Indicator_DMA" />
                  <option text="TRIX" name="Indicator_TRIX" />
                  <option text="CCI" name="Indicator_CCI" />
                </select>
                <select name="cbPlot" selectedindex="0" size="100,25">
                  <option text="直线" name="Plot_Line" />
                  <option text="线段" name="Plot_Segment" />
                  <option text="射线" name="Plot_Ray" />
                  <option text="三角形" name="Plot_Triangle" />
                  <option text="矩形" name="Plot_Rect" />
                  <option text="圆" name="Plot_Cycle" />
                  <option text="外接圆" name="Plot_CircumCycle" />
                  <option text="椭圆" name="Plot_Ellipse" />
                  <option text="角度线" name="Plot_AngleLine" />
                  <option text="线性回归" name="Plot_LRLine" />
                  <option text="线性回归通道" name="Plot_LRChannel" />
                  <option text="对称三角形" name="Plot_SymmetricTriangle" />
                  <option text="线性回归带" name="Plot_LRBand" />
                  <option text="平行四边形" name="Plot_ParalleGram" />
                  <option text="速阻线" name="Plot_SpeedResist" />
                  <option text="斐波扇面" name="Plot_FiboFanline" />
                  <option text="斐波周期线" name="Plot_FiboTimezone" />
                  <option text="百分比线" name="Plot_Percent" />
                  <option text="箱型线" name="Plot_BoxLine" />
                  <option text="泰龙水平线" name="Plot_TironeLevels" />
                  <option text="四等分线" name="Plot_QuadrantLines" />
                  <option text="平行线" name="Plot_Parallel" />
                  <option text="黄金分割线" name="Plot_GoldenRatio" />
                  <option text="箭头线段" name="Plot_ArrowSegment" />
                </select>
              </div>
                <chart size="200,200" name="Chart" text="Chart" dock="Fill"/>
            </div>
          </body>
        </html>`;
        renderFaceCat(gPaint, xml);
        let chart = findViewByName("Chart", gPaint.views);
        chart.leftVScaleWidth = 70;
        chart.rightVScaleWidth = 70;
        chart.vScaleDistance = 35;
        chart.hScalePixel = 11;
        chart.hScaleHeight = 30;
        chart.candlePaddingTop = 30;
        chart.candlePaddingBottom = 20;
        chart.volPaddingTop = 20;
        chart.volPaddingBottom = 0;
        chart.vScaleDistance = 35;
        chart.dock = "fill";
        chart.mainIndicator = "BOLL";
        chart.showIndicator = "BIAS";
        chart.allowDragChartDiv = true;
        if (gPaint.isMobile) {
            chart.rightVScaleWidth = 0;
            chart.leftVScaleWidth = 60;
        }

        /*
        * 黑色风格
        */
        let toBlackChart = function () {
            chart.backColor = "rgb(0,0,0)";
            chart.borderColor = "none";
            chart.textColor = "rgb(255,255,255)";
            chart.scaleColor = "rgb(75,75,75)";
            chart.crossTipColor = "rgb(50,50,50)";
            chart.crossLineColor = "rgb(100,100,100)";
            chart.gridColor = "rgb(50,50,50)";
            chart.trendColor = "rgb(255,255,255)";
            chart.indicatorColors = new Array();
            chart.indicatorColors.push("rgb(255,255,255)");
            chart.indicatorColors.push("rgb(255,255,0)");
            chart.indicatorColors.push("rgb(255,0,255)");
            chart.indicatorColors.push("rgb(255,0,0)");
            chart.indicatorColors.push("rgb(0,255,255)");
            chart.indicatorColors.push("rgb(0,255,0)");
            chart.indicatorColors.push("rgb(255,255,0)");
            chart.indicatorColors.push("rgb(255,255,255)");
            for (let i = 0; i < chart.plots.length; i++) {
                let plot = chart.plots[i];
                plot.lineColor = "rgb(255,255,255)";
                plot.pointColor = "rgba(255,255,255,125)";
            }
        };

        toBlackChart();
        invalidateView(chart);

        //请求历史数据
        let queryHistoryData = function () {
            let url = "https://web.ifzq.gtimg.cn/appstock/app/fqkline/get?_var=kline_dayqfq&param=sh601857,day,,,320,qfq&r=0.9860043111257255";
            let xmlhttp = new XMLHttpRequest();
            xmlhttp.open("GET", url, true);
            xmlhttp.onreadystatechange = function () {
                if (xmlhttp.readyState === 4 && xmlhttp.status === 200) {
                    let result = xmlhttp.responseText;
                    let dataList = new Array();
                    let datas = result.split("[");
                    for (let i = 0; i < datas.length; i++) {
                        let subDatas = datas[i].split(",");
                        if (subDatas.length == 7) {
                            let data = new SecurityData();
                            let date = new Date(subDatas[0].replaceAll("'", "").replaceAll("\"", ""));
                            data.close = parseFloat(subDatas[2].replaceAll("'", "").replaceAll("\"", ""));
                            data.high = parseFloat(subDatas[3].replaceAll("'", "").replaceAll("\"", ""));
                            data.low = parseFloat(subDatas[4].replaceAll("'", "").replaceAll("\"", ""));
                            data.open = parseFloat(subDatas[1].replaceAll("'", "").replaceAll("\"", ""));
                            data.volume = parseFloat(subDatas[5].replaceAll("'", "").replaceAll("\"", ""));
                            data.date = date.getTime();
                            dataList.push(data);
                        }
                    }
                    chart.datas = dataList;
                    chart.text = "601857 中国石油 日线";
                    let maxVisibleRecord = getChartMaxVisibleCount(chart, chart.hScalePixel, getChartWorkAreaWidth(chart));
                    chart.lastVisibleIndex = chart.datas.length - 1;
                    if (maxVisibleRecord > chart.datas.length) {
                        chart.firstVisibleIndex = 0;
                    } else {
                        chart.firstVisibleIndex = chart.lastVisibleIndex - maxVisibleRecord + 1;
                    }
                    resetChartVisibleRecord(chart);
                    checkChartLastVisibleIndex(chart);
                    calcChartIndicator(chart);
                    invalidateView(chart);
                }
            }
            xmlhttp.send(null);
        };

        queryHistoryData();
    </script>

</body>
</html>
